/*
 * KKDirector.cpp
 *
 *  Created on: 2013-9-7
 *      Author: wh
 */

#include "KKDirector.h"

#include "KKAudioManager.h"

#include "KKLayout.h"

#include <iostream>

USING_NS_CC;

using namespace std;

KKDirector* KKDirector::kk_share_director;
bool KKDirector::isDebug = false;

int KKDirector::screenWidth = 1920;
int KKDirector::screenHeight = 1200;

const char* KKDirector::getVersion() {
	return "v0.99.10";
}

// on "init" you need to initialize your instance
bool KKDirector::init() {

	CCLog("KAKA KKDirector init\n");

	CCDirector::sharedDirector()->setDepthTest(false);

	KKNodeParser::registerParser("Text", new KKTextParser());
	KKNodeParser::registerParser("EditText", new KKEditTextParser());
	KKNodeParser::registerParser("Sprite", new KKSpriteParser());
	KKNodeParser::registerParser("Layer", new KKLayerParser());
	//KKNodeParser::registerParser("GridView", new KKGridViewParser());
	//KKNodeParser::registerParser("Canvas", new KKCanvasParser());
	//KKNodeParser::registerParser("Gallery", new KKGalleryParser());

	//KKNodeParser::registerParser("Background", new KKBackgroundParser());
	//KKNodeParser::registerParser("PhotoGallery", new PhotoGalleryParser());
	//KKNodeParser::registerParser("ImageGallery", new ImageGalleryParser());
	//KKNodeParser::registerParser("Dialog", new KKDialogParser());

	KKLayoutParser::registerParser("RelativeLayout",
			new RelativeLayoutParser());
	KKLayoutParser::registerParser("LinearLayout", new LinearLayoutParser());
	KKLayoutParser::registerParser("GridLayout", new GridLayoutParser());
	KKLayoutParser::registerParser("AbsLayout", new AbsLayoutParser());

	KKDirector::kk_share_director = this;

	CCDirector::sharedDirector()->getKeypadDispatcher()->addDelegate(this);
	CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(
			this, 1, false);

	KKTime::initStarupTime();

	KKAudioManager::sharedAudioManager()->init();

	srand((unsigned) time(0));

	return true;
}

void KKDirector::loadProject(const char* projectFile) {
	CCLog("KAKA project %s \n", projectFile);

	TiXmlDocument *myDocument = XmlUtils::readXML(projectFile);

	CCLog("KAKA loaded project \n");

	TiXmlElement *rootElement = myDocument->RootElement();

	TiXmlElement * childElement = rootElement->FirstChildElement("scene");

	const char* firstScene = NULL;
	const char* name = NULL;
	const char* path = NULL;

	while (childElement != NULL) {

		name = childElement->Attribute("name");
		path = childElement->Attribute("path");

		KKScene* scene = KKScene::sceneWithFile(name, path);

		if (scene) {

			CCLog("scene %s\n", scene->getName().c_str());

			m_scenes->setObject(scene, scene->getName());

			if (firstScene == NULL) {
				firstScene = name;
			}
		}

		childElement = childElement->NextSiblingElement("scene");
	}

	this->m_scene = this->sceneNamed(firstScene);
	this->m_scene->loadScene();
}

void KKDirector::executeFunc(CCNode* target, string funcName, void* args) {
	if (!funcName.empty()) {
		KKEventHandler* handler = m_events->objectForKey(funcName);
		if (handler) {
			handler->handle(target, args);
		} else {
			CCLog("未找到方法%s\n", funcName.c_str());
		}
	}
}

void KKDirector::runStoryboard(string storyboardName, void* args) {
	if (!storyboardName.empty()) {
		KKStoryboard * storyboard = this->getCurrentScene()->storyboardNamed(
				storyboardName);

		if (storyboard) {
			storyboard->start();
		} else {
			CCLog("未找到storyboard=%s\n", storyboardName.c_str());
		}
	}
}

void KKDirector::pauseStoryboard(string storyboardName, void* args) {
	if (!storyboardName.empty()) {
		KKStoryboard * storyboard = this->getCurrentScene()->storyboardNamed(
				storyboardName);

		if (storyboard) {
			storyboard->pause();
		}
	}
}

void KKDirector::resumeStoryboard(string storyboardName, void* args) {
	if (!storyboardName.empty()) {
		KKStoryboard * storyboard = this->getCurrentScene()->storyboardNamed(
				storyboardName);

		if (storyboard) {
			storyboard->resume();
		}
	}
}

void KKDirector::stopStoryboard(string storyboardName, void* args) {
	if (!storyboardName.empty()) {
		KKStoryboard * storyboard = this->getCurrentScene()->storyboardNamed(
				storyboardName);

		if (storyboard) {
			storyboard->stop();
		}
	}
}

void KKDirector::loadSound(const char* path, bool music) {
	if (path) {
		if (music) {
			if (m_enableMusicEffect) {
				KKAudioManager::sharedAudioManager()->loadBackgroudMusic(path);
			}

		} else {

			if (m_enableSoundEffect) {

				KKAudioManager::sharedAudioManager()->load(path);
			}

		}
	}
}

void KKDirector::playSound(const char* path, bool music, int loop,
		KKCallback* endCallback) {

	if (path) {

		if (KKDirector::isDebug) {
			CCLog("play sound %s loop=%d\n", path, loop);
		}

		if (music) {

			if (m_enableMusicEffect) {

				KKAudioManager::sharedAudioManager()->playBackgroudMusic(path,
						loop);
			}

		} else {

			if (m_enableSoundEffect) {

				KKAudioManager::sharedAudioManager()->play(path, loop,
						endCallback);

			}

		}

	}
}

void KKDirector::stopSound(const char* path, bool music) {

	if (path) {

		if (KKDirector::isDebug) {
			CCLog("stop sound %s\n", path);
		}

		if (music) {
			KKAudioManager::sharedAudioManager()->stopBackgroudMusic();
		} else {
			KKAudioManager::sharedAudioManager()->stop(path);
		}

	} else {

		if (music) {
			KKAudioManager::sharedAudioManager()->stopBackgroudMusic();
		} else {
			KKAudioManager::sharedAudioManager()->stopAll();
		}

	}
}

void KKDirector::pauseSound(const char* path, bool music) {
	if (path) {

		if (KKDirector::isDebug) {
			CCLog("pause sound %s\n", path);
		}

		if (music) {
			KKAudioManager::sharedAudioManager()->pauseBackgroudMusic();
		} else {
			KKAudioManager::sharedAudioManager()->pause(path);
		}

	} else {

		if (music) {
			KKAudioManager::sharedAudioManager()->pauseBackgroudMusic();
		} else {
			KKAudioManager::sharedAudioManager()->pauseAll();
		}

	}
}

void KKDirector::resumeSound(const char* path, bool music) {
	if (path) {

		if (KKDirector::isDebug) {
			CCLog("resume sound %s\n", path);
		}

		if (music) {
			KKAudioManager::sharedAudioManager()->resumeBackgroudMusic();
		} else {
			KKAudioManager::sharedAudioManager()->resume(path);
		}

	} else {

		if (music) {
			KKAudioManager::sharedAudioManager()->pauseBackgroudMusic();
		} else {
			KKAudioManager::sharedAudioManager()->resumeAll();
		}

	}
}

void KKDirector::adjustSoundVolumn(const char* path, bool music, float volume) {

	if (KKDirector::isDebug) {
		CCLog("adjustSoundVolumn sound %f\n", volume);
	}

	if (music) {
		KKAudioManager::sharedAudioManager()->setBackgroundVolume(volume);
	} else {
		KKAudioManager::sharedAudioManager()->setVolume(path, volume);
	}
}

void KKDirector::pause() {
	this->getCurrentScene()->pauseNode();
}

void KKDirector::resume() {
	this->getCurrentScene()->resumeNode();
}

void KKDirector::loadImages(const char* image, ...) {
	va_list args;

	va_start(args, image);

	const char* path = va_arg(args,const char*);

	if (image) {
		CCTextureCache::sharedTextureCache()->addImageAsync(image, this,
		callfuncO_selector(KKDirector::onImageLoaded));
	}

	while (path) {
		CCTextureCache::sharedTextureCache()->addImageAsync(path, this,
		callfuncO_selector(KKDirector::onImageLoaded));
		path = va_arg(args,const char*);
	}

	va_end(args);
}

void KKDirector::onImageLoaded(CCObject* obj) {
	//xxxxxxxxxx
	//CCTextureInfo* texture = dynamic_cast<CCTextureInfo*>(obj);
	//texture->texture->retain();
	CCLog("time %s\n ", KKTime::getCurrentTime().format());
}

void KKDirector::exitApp(CCNode* pSender, void* args) {

	KKAudioManager::sharedAudioManager()->destory();

	CCDirector::sharedDirector()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

	exit(-1);

#endif  // CC_PLATFORM_IOS
}

void KKDirector::setTargetProperty(CCNode* pSender, void* args) {
	KKNode* sprite = dynamic_cast<KKNode*>(pSender);
	if (sprite) {

		KKEventActionArgs* allArgs = (KKEventActionArgs*) args;

		KKPropertiesDictionary* dict = allArgs->getArgs();

		if (dict) {

			vector<string> keys = dict->allKeys();

			vector<string>::iterator it = keys.begin();

			string key;

			CCString* value;

			while (it != keys.end()) {

				key = *it;

				value = dict->objectForKey(key);

				if (key == "enabled") {
					sprite->setIsEnable(value->m_sString == "true");
				} else if (key == "clickable") {
					sprite->setIsTouchable(value->m_sString == "true");
				} else if (key == "movable") {
					sprite->setIsMovable(value->m_sString == "true");
				} else if (key == "selected") {
					sprite->setSelected(value->m_sString == "true");
				} else if (key == "visible") {
					sprite->setIsVisible(value->m_sString == "true");
				} else if (key == "enabled") {
					sprite->setIsEnable(value->m_sString == "true");
				} else if (key == "name") {
					sprite->setName(value->m_sString);
				} else if (key == "image") {
					dynamic_cast<KKSprite*>(sprite)->setTextureFile(
							value->m_sString.c_str());
				}

				sprite->setProperty(key, value->m_sString.c_str());

				it++;

			}
		}

	}
}

void KKDirector::resetTarget(CCNode* pSender, void* args) {

	KKNode* sprite = dynamic_cast<KKNode*>(pSender);
	if (sprite) {

		KKEventActionArgs* allArgs = (KKEventActionArgs*) args;
		CCString* reload = allArgs->getArgs()->objectForKey("reload");
		sprite->resetNode(reload && reload->m_sString == "true");
	}

}

void KKDirector::showFocus(CCNode* pSender, void* args) {
	setSelected(pSender, args);
}

void KKDirector::loseFocus(CCNode* pSender, void* args) {
	setUnselected(pSender, args);
}

void KKDirector::setSelected(CCNode* pSender, void* args) {
	KKSprite* sprite = dynamic_cast<KKSprite*>(pSender);
	if (sprite) {
		sprite->setSelected(true);
	}
}

void KKDirector::setUnselected(CCNode* pSender, void* args) {

	KKSprite* sprite = dynamic_cast<KKSprite*>(pSender);
	if (sprite) {
		sprite->setSelected(false);
	}
}

void KKDirector::showTarget(CCNode* pSender, void* args) {

	KKScene* scene = dynamic_cast<KKScene*>(pSender);

	if (scene) {

		KKEventActionArgs* myargs = (KKEventActionArgs*) args;

		CCString* transition = myargs->getArgs()->objectForKey("transition");
		CCString* operate = myargs->getArgs()->objectForKey("operate");
		CCString* durationInt = myargs->getArgs()->objectForKey("duration");

		KKSceneTransitionMode mode = NONE;
		float duration = 800;
		bool push = false;

		if (transition) {

			if (transition->m_sString == "FADE_IN") {
				mode = FADE_IN;
			} else if (transition->m_sString == "FLIP_LEFT") {
				mode = FLIP_LEFT;
			} else if (transition->m_sString == "FLIP_RIGHT") {
				mode = FLIP_RIGHT;
			} else if (transition->m_sString == "FLIP_UP") {
				mode = FLIP_UP;
			} else if (transition->m_sString == "FLIP_DOWN") {
				mode = FLIP_DOWN;
			} else if (transition->m_sString == "SHRINK_GROW") {
				mode = SHRINK_GROW;
			} else if (transition->m_sString == "MOVE_IN_L") {
				mode = MOVE_IN_L;
			} else if (transition->m_sString == "MOVE_IN_R") {
				mode = MOVE_IN_R;
			} else if (transition->m_sString == "MOVE_IN_T") {
				mode = MOVE_IN_T;
			} else if (transition->m_sString == "MOVE_IN_B") {
				mode = MOVE_IN_B;
			} else if (transition->m_sString == "SLIDE_L") {
				mode = SLIDE_L;
			} else if (transition->m_sString == "SLIDE_R") {
				mode = SLIDE_R;
			} else if (transition->m_sString == "SLIDE_T") {
				mode = SLIDE_T;
			} else if (transition->m_sString == "SLIDE_B") {
				mode = SLIDE_B;
			} else if (transition->m_sString == "CROSS") {
				mode = CROSS;
			} else if (transition->m_sString == "RADIAL_CCW") {
				mode = RADIAL_CCW;
			} else if (transition->m_sString == "RADIAL_CW") {
				mode = RADIAL_CW;
			} else if (transition->m_sString == "PAGE_FORWARD") {
				mode = PAGE_FORWARD;
			} else if (transition->m_sString == "PAGE_BACK") {
				mode = PAGE_BACK;
			}

		}

		if (operate) {
			push = operate->m_sString == "PUSH";
		}
		if (durationInt) {
			duration = durationInt->intValue() / 1000.0;
		}

		this->showScene(scene, push, mode, duration);

	} else {
		pSender->setVisible(true);
	}

}

void KKDirector::hideTarget(CCNode* pSender, void* args) {

	KKScene* scene = dynamic_cast<KKScene*>(pSender);

	if (scene) {
		this->hideScene(scene);
	} else {
		pSender->setVisible(false);
	}

}

void KKDirector::toggleTarget(CCNode* pSender, void* args) {

	pSender->setVisible(!pSender->isVisible());

}

void KKDirector::fadeInTarget(CCNode* pSender, void* args) {
	showTarget(pSender, args);

	pSender->runAction(CCFadeIn::create(ccTime(1)));

}

void KKDirector::fadeOutTarget(CCNode* pSender, void* args) {

	pSender->runAction(
			CCSequence::create(CCFadeOut::create(ccTime(1)),
					CCCallFuncND::create(this,
					callfuncND_selector(KKDirector::hideTarget), args),
					NULL));

}

void KKDirector::enableTarget(CCNode* pSender, void* args) {
	KKNode* sprite = dynamic_cast<KKNode*>(pSender);
	if (sprite) {
		sprite->setIsEnable(true);
	}
}

void KKDirector::disableTarget(CCNode* pSender, void* args) {
	KKNode* sprite = dynamic_cast<KKNode*>(pSender);
	if (sprite) {
		sprite->setIsEnable(false);
	}
}

bool KKDirector::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {

	//	CCLog("ccTouchBegan viewid=%d\n", pTouch->id());

	KKTouch touch = KKTouch(pTouch);

	if (this->getCurrentScene()->getIsEnable()) {
		return this->getCurrentScene()->dispatchTouchDown(touch);
	}

	return false;

}

void KKDirector::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {

	if (this->getCurrentScene()->isInTouch(pTouch->getID())) {
		KKTouch touch = KKTouch(pTouch);
		this->getCurrentScene()->dispatchTouchMove(touch);
	} else {
		CCLog("ccTouchMoved viewid=%d\n", pTouch->getID());
	}

}

void KKDirector::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {

	//	CCLog("ccTouchEnded viewid=%d\n", pTouch->id());

	if (this->getCurrentScene()->isInTouch(pTouch->getID())) {
		KKTouch touch = KKTouch(pTouch);
		this->getCurrentScene()->dispatchTouchUp(touch);
	} else {
		CCLog("ccTouchEnded viewid=%d\n", pTouch->getID());
	}

}

void KKDirector::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent) {

	if (this->getCurrentScene()->isInTouch(pTouch->getID())) {
		KKTouch touch = KKTouch(pTouch);
		this->getCurrentScene()->dispatchTouchCancel(touch);
	} else {
		CCLog("ccTouchCancelled viewid=%d\n", pTouch->getID());
	}

}

